﻿using System;
using System.IO;
using System.Net;

namespace Coding4Fun.Cannon.Phone.Service
{
	public class PassData
    {
        public HttpWebRequest Request { get; set; }
        public ServiceCompletedCallback Callback { get; set; }
    }

	public delegate void ServiceCompletedCallback(object sender, ServiceCompletedEventArgs e);

    public class CannonService
    {
		public CannonService(Settings settings)
		{
			_endpointUrl = settings.EndpointUrl; // @"http://betty2/betty/default.aspx";
			_endpointUrlDirectory = !settings.UseRcCar ? "betty" : "rc";
		}

    	private readonly string _endpointUrl;
		private readonly string _endpointUrlDirectory;
		
        #region Fire Commands

		public void Fire()
        {
			CallService(ServerCommands.fire);
        }

        #endregion
		
		#region Init Command
		
		public void Init(ServiceCompletedCallback callback)
		{
			CallService(ServerCommands.init, callback: callback, readResults: true);
		}
		#endregion

        #region Drive Command
        public void Drive(int leftPower, int rightPower)
        {
			CallService(ServerCommands.drive, "leftpower={0}&rightpower={1}", null, false, leftPower, rightPower);
        } 
        #endregion

        #region Pan & Tilt Commands
        public void Pan(double pan)
        {
			CallService(ServerCommands.aim, "pan={0}", null, false, pan);
        }

        public void Tilt(double tilt)
        {
			CallService(ServerCommands.aim, "tilt={0}", null, false, tilt);

        }

        public void PanAndTilt(double pan, double tilt)
        {
            CallService(ServerCommands.aim, "pan={0}&tilt={1}", null, false, pan, tilt );
        }
        #endregion


		#region Web Calls

		private void CallService(ServerCommands command, string format = "", ServiceCompletedCallback callback = null, bool readResults = false, params object[] args)
		{
			var request = (HttpWebRequest)WebRequest.Create(string.Format("http://{0}/{1}/?command={2}&ticks={3}&", _endpointUrl, _endpointUrlDirectory, command, DateTime.Now.Ticks) + string.Format(format.TrimStart('&'), args));
			request.Method = "GET";

			var data = new PassData {Request = request, Callback = callback};

// if we are debugging, output information may be useful.
#if DEBUG
			Logger.WriteLine(String.Format("Starting CallService: url:{0} callback:{1}", request.RequestUri.OriginalString, callback));
			if (!readResults)
			{
				request.BeginGetResponse(CallBackNoResults, data);

			}
			else
#endif
			{
				request.BeginGetResponse(CallBackWithResults, data);
			}
		}

    	static void CallBackNoResults(IAsyncResult result)
		{
			var data = (PassData) result.AsyncState;

			try
			{
				if (data.Callback != null)
					data.Callback(null, null);
			}
			catch (WebException wEx)
			{
				Logger.WriteLine(String.Format("WebException: Status:{0}", wEx.Status), MessageType.Error);
				Logger.WriteLine(wEx.Message, MessageType.Error);
			}
		}

		void CallBackWithResults(IAsyncResult result)
		{
			var data = (PassData)result.AsyncState;

			try
			{
				string html;
				var response = (data.Request).EndGetResponse(result);

				Logger.WriteLine(String.Format("Ending CallService: url:{0} callback:{1}", data.Request.RequestUri.OriginalString, data.Callback));
				using (var sr = new StreamReader(response.GetResponseStream()))
					html = sr.ReadToEnd();

				//call delegate and pass result
				if (data.Callback != null)
					data.Callback(this, new ServiceCompletedEventArgs(html, null));
			}
			catch (WebException wEx)
			{
				Logger.WriteLine(String.Format("WebException: Status:{0}", wEx.Status), MessageType.Error);
				Logger.WriteLine(wEx.Message, MessageType.Error);
			}
		}
        #endregion

		private enum ServerCommands
		{
			aim,
			fire,
			drive,
			init
		}
    }
}
